package game.coord;

import game.games.carcassonne.IterablePoint;

import java.awt.Dimension;
import java.awt.Point;

public class MultiArrayContainer<TYPE>
{
    private Dimension  size;
    private Object[][] values;
    
    public MultiArrayContainer(Dimension size)
    {
        setSize(size);
    }
    
    public void setValue(Point position, TYPE value)
    {
        this.values[position.y][position.x] = value;
    }
    
    @SuppressWarnings("unchecked")
    public TYPE getValue(Point position)
    {
        return (TYPE) values[position.y][position.x];
    }
    
    public void setSize(Dimension size)
    {
        this.size = size;
        this.values = new Object[size.height][size.width];
    }
    
    public Dimension getSize()
    {
        return this.size;
    }
    
    public int countValues()
    {
        return size.width * size.height;
    }
    
    public IterablePoint<TYPE> getIterator()
    {
        return new IterablePoint<TYPE>() {
            private int x = 0;
            private int y = 0;
            
            @Override
            public Point getCurrentPoint()
            {
                Point point = new Point(x, y);
                return point;
            }
            
            private Point getNextPoint()
            {
                int nextX = x + 1;
                int nextY = y;
                // next line?
                if (nextX == getSize().width)
                {
                    nextX = 0;
                    nextY++;
                }
                // over the last line?
                if (nextY == getSize().height)
                {
                    nextX = 0;
                    nextY = 0;
                }
                return new Point(nextX, nextY);
            }
            
            @Override
            public boolean hasNext()
            {
                if (x == -1 && y == -1)
                {
                    return false;
                }
                return true;
            }
            
            @Override
            public TYPE next()
            {
                TYPE current = getValue(new Point(x, y));
                Point next = getNextPoint();
                if (next.equals(new Point(0, 0)))
                {
                    x = -1;
                    y = -1;
                }
                else
                {
                    x = next.x;
                    y = next.y;
                }
                return current;
            }
            
            @Override
            public void remove()
            {
                setValue(new Point(x, y), null);
            }
        };
    }
}
